#include "../test_helpers.h"
#include "EncryptionHelper.h"
#include <spdlog/spdlog.h>
#include <gtest/gtest.h>

using namespace MessageFramework;
using namespace MessageFramework::Test;

class EncryptionHelperTest : public ::testing::Test {
protected:
    std::string key;

    void SetUp() override {
        spdlog::set_level(spdlog::level::debug);
        key = EncryptionHelper::generateKey();  // 生成测试密钥
    }
};

// ==================== 密钥生成测试 ====================

TEST_F(EncryptionHelperTest, GenerateKey) {
    std::string key1 = EncryptionHelper::generateKey();
    std::string key2 = EncryptionHelper::generateKey();

    // 密钥应该唯一
    EXPECT_NE(key1, key2);

    // 密钥长度应该是64个十六进制字符（32字节）
    EXPECT_EQ(key1.length(), 64);
    EXPECT_EQ(key2.length(), 64);
}

// ==================== 加密/解密测试 ====================

TEST_F(EncryptionHelperTest, EncryptDecrypt) {
    std::string plaintext = "Hello, MessageFramework!";

    // 加密
    std::string ciphertext = EncryptionHelper::encrypt(plaintext, key);
    EXPECT_GT(ciphertext.length(), 0);
    EXPECT_NE(plaintext, ciphertext);  // 密文应该不同于明文

    // 解密
    std::string decrypted = EncryptionHelper::decrypt(ciphertext, key);
    EXPECT_EQ(plaintext, decrypted);
}

TEST_F(EncryptionHelperTest, EncryptLongText) {
    std::string plaintext(10000, 'A');  // 10KB文本

    std::string ciphertext = EncryptionHelper::encrypt(plaintext, key);
    std::string decrypted = EncryptionHelper::decrypt(ciphertext, key);

    EXPECT_EQ(plaintext, decrypted);
}

TEST_F(EncryptionHelperTest, EncryptEmptyString) {
    std::string plaintext = "";

    std::string ciphertext = EncryptionHelper::encrypt(plaintext, key);
    std::string decrypted = EncryptionHelper::decrypt(ciphertext, key);

    EXPECT_EQ(plaintext, decrypted);
}

TEST_F(EncryptionHelperTest, EncryptSpecialCharacters) {
    std::string plaintext = "测试中文字符 !@#$%^&*()_+ \n\t";

    std::string ciphertext = EncryptionHelper::encrypt(plaintext, key);
    std::string decrypted = EncryptionHelper::decrypt(ciphertext, key);

    EXPECT_EQ(plaintext, decrypted);
}

// ==================== 加密唯一性测试 ====================

TEST_F(EncryptionHelperTest, EncryptionRandomIV) {
    std::string plaintext = "same plaintext";

    // 相同明文加密两次应该得到不同密文（因为IV随机）
    std::string ciphertext1 = EncryptionHelper::encrypt(plaintext, key);
    std::string ciphertext2 = EncryptionHelper::encrypt(plaintext, key);

    EXPECT_NE(ciphertext1, ciphertext2);

    // 但解密后都应该得到原始明文
    EXPECT_EQ(EncryptionHelper::decrypt(ciphertext1, key), plaintext);
    EXPECT_EQ(EncryptionHelper::decrypt(ciphertext2, key), plaintext);
}

// ==================== 错误处理测试 ====================

TEST_F(EncryptionHelperTest, DecryptWithWrongKey) {
    std::string plaintext = "secret message";
    std::string ciphertext = EncryptionHelper::encrypt(plaintext, key);

    std::string wrongKey = EncryptionHelper::generateKey();
    std::string decrypted = EncryptionHelper::decrypt(ciphertext, wrongKey);

    // 错误密钥应该解密失败（返回空字符串）
    EXPECT_EQ(decrypted, "");
}

TEST_F(EncryptionHelperTest, DecryptInvalidCiphertext) {
    std::string invalidCiphertext = "this is not a valid ciphertext";

    std::string decrypted = EncryptionHelper::decrypt(invalidCiphertext, key);

    // 无效密文应该解密失败
    EXPECT_EQ(decrypted, "");
}

TEST_F(EncryptionHelperTest, DecryptTamperedCiphertext) {
    std::string plaintext = "original message";
    std::string ciphertext = EncryptionHelper::encrypt(plaintext, key);

    // 篡改密文（修改Base64字符串中的一个字符）
    if (ciphertext.length() > 10) {
        ciphertext[10] = (ciphertext[10] == 'A') ? 'B' : 'A';
    }

    std::string decrypted = EncryptionHelper::decrypt(ciphertext, key);

    // GCM模式会检测篡改，解密应该失败
    EXPECT_EQ(decrypted, "");
}

// ==================== Base64编解码测试 ====================

TEST_F(EncryptionHelperTest, Base64EncodeDecode) {
    std::vector<unsigned char> data = {'H', 'e', 'l', 'l', 'o'};

    std::string encoded = EncryptionHelper::base64Encode(data);
    EXPECT_GT(encoded.length(), 0);

    std::vector<unsigned char> decoded = EncryptionHelper::base64Decode(encoded);
    EXPECT_EQ(data, decoded);
}

int main(int argc, char** argv) {
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
